home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / metamail / contrib / mms / mmsclient.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  9.6 KB  |  484 lines

  1. /*////////////////////////////////////////////////////////////////////////
  2. Copyright (c) 1992 Electrotechnical Laboratry (ETL)
  3.  
  4. Permission to use, copy, modify, and distribute this material 
  5. for any purpose and without fee is hereby granted, provided 
  6. that the above copyright notice and this permission notice 
  7. appear in all copies, and that the name of ETL not be 
  8. used in advertising or publicity pertaining to this 
  9. material without the specific, prior written permission 
  10. of an authorized representative of ETL.
  11. ETL MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY 
  12. OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", 
  13. WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
  14. /////////////////////////////////////////////////////////////////////////
  15. Content-Type: program/C; charset=US-ASCII
  16. Program:      mmsclient (client library to access remote mms server)
  17. Author:       Yutaka Sato <ysato@etl.go.jp>
  18.  
  19. History:
  20.   v0.1  92.04.29     created a small prototype
  21. ///////////////////////////////////////////////////////////////////////*/
  22.  
  23. #include <stdio.h>
  24. FILE *tmpfile();
  25. char *index(),*getenv();
  26.  
  27. /*//////////////////////////////////////////////////////////////////////*/
  28.  
  29. MMS_E_client(ac,av,in,out){
  30.     MMS_client(ac,av,in);
  31. }
  32. int (*MMS_E_CLIENT)() = MMS_E_client;
  33.  
  34. /*//////////////////////////////////////////////////////////////////////*/
  35. #define MMS_PORT_NAME    "mms"
  36.  
  37. #define OK_GOODBYE 205
  38. MMS_goodbye(stat){ return stat == OK_GOODBYE; }
  39. #define CONT_INPUT 390
  40. MMS_sendbody(stat){ return stat == CONT_INPUT; }
  41. #define ERR_CONT_INPUT 596
  42. MMS_discardbody(stat){ return stat == ERR_CONT_INPUT; }
  43.  
  44. typedef struct {
  45.     char    *host;
  46.     FILE    *serv;
  47. } MMS_Server;
  48.  
  49. int MMS_DEBUG;
  50. MMS_client(ac,av,in)
  51.     char *av[];
  52.     FILE *in;
  53. {    char line[2048];
  54.     FILE *serv[2];
  55.     int stat = 0;
  56.     static int IsaTty;
  57.  
  58.     ac = MMS_clientstart(ac,av,serv);
  59.     if( 1 < ac ){
  60.         int ai;
  61.  
  62.         for( ai = 1; ai < ac; ai++ ){
  63.             if( MMS_discardbody(stat) ){}else
  64.             if( MMS_sendbody(stat) ){
  65.                 MMS_putserver_file(serv,in,av[ai]);
  66.                 stat = MMS_getserver(serv);
  67.             }else{
  68.                 if( MMS_putserver(serv,"%s\n",av[ai]) != 0 )
  69.                     break;
  70.                 stat = MMS_getserver(serv);
  71.             }
  72.             if( MMS_goodbye(stat) )
  73.                 break;
  74.         }
  75.         return 0;
  76.     }
  77.     for(;;){
  78.         IsaTty = isatty(fileno(in));
  79.         if( IsaTty ){
  80.             printf("command> ");
  81.             fflush(stdout);
  82.         }
  83.         if( fgets(line,sizeof(line),in) == NULL )
  84.             break;
  85.         if( *line == '\n' )
  86.             continue;
  87.  
  88.         if( MMS_putserver(serv,"%s",line) != 0 )
  89.             break;
  90.  
  91.         stat = MMS_getserver(serv);
  92.         if( MMS_sendbody(stat) ){
  93.             send_body(serv,in);
  94.             stat = MMS_getserver(serv);
  95.         }
  96.         if( MMS_goodbye(stat) )
  97.             break;
  98.     }
  99.     return 0;
  100. }
  101. static send_body(serv,in)
  102.     FILE *serv[];
  103.     FILE *in;
  104. {    int Isatty = isatty(fileno(in));
  105.     char line[2048];
  106.     int lines = 0;
  107.  
  108.     for(;;){
  109.         lines++;
  110.         if( Isatty ){
  111.             printf("input> ");
  112.             fflush(stdout);
  113.         }
  114.         if( fgets(line,sizeof(line),in) == NULL )
  115.             break;
  116.  
  117.         if( lines == 1 ){
  118.             if( line[0] == '<' || line[0] == '!' ){
  119.                 char file[1024];
  120.  
  121.                 if( line[0] == '<' )
  122.                     sscanf(line+1,"%s",file);
  123.                 else    strcpy(file,line);
  124.                 MMS_putserver_file(serv,in,file);
  125.                 break;
  126.             }
  127.         }
  128.  
  129.         MMS_putserver(serv,"%s",line);
  130.         if( strcmp(line,".\n") == 0 )
  131.             break;
  132.     }
  133. }
  134. MMS_putserver_file(serv,in,srcfile)
  135.     FILE *serv[],*in;
  136.     char *srcfile;
  137. {    FILE *srcfp;
  138.  
  139.     if( strcmp(srcfile,"-") == 0 )
  140.         srcfp = fdopen(fileno(in),"r");
  141.     else
  142.     if( *srcfile == '!' )
  143.         srcfp = popen(srcfile+1,"r");
  144.     else    srcfp = fopen(srcfile,"r");
  145.  
  146.     if( srcfp != NULL ){
  147. /*
  148.         MMS_encodeBASE16(srcfp,serv[1]);
  149. */
  150.         to64(srcfp,serv[1]);
  151.         fprintf(serv[1],".\n");
  152.     }else    fprintf(serv[1],".\n");
  153.     fflush(serv[1]);
  154.     fclose(srcfp);
  155. }
  156.  
  157. /*////////////////////////////////////////////////////////////////////////
  158.  */
  159. MMS_clientstart(ac,av,serv)
  160.     char *av[];
  161.     FILE *serv[];
  162. {    int ai;
  163.     int sock;
  164.     char *hostname[256],*hn;
  165.  
  166.     ac = MMS_gethostarg(ac,av,hostname);
  167.     if( *hostname == 0 ){
  168.         if( hn = getenv("MMSERVER") )
  169.             strcpy(hostname,hn);
  170.         else    gethostname(hostname,sizeof hostname);
  171.     }
  172.     sock = open_MMS_server(hostname);
  173.     serv[0] = fdopen(sock,"r"); setlinebuf(serv[0]);
  174.     serv[1] = fdopen(sock,"w"); setlinebuf(serv[1]);
  175.     MMS_getserver(serv);
  176.     MMS_authenticate(serv);
  177.     return ac;
  178. }
  179. MMS_gethostarg(ac,av,hostnameb)
  180.     char *av[],*hostnameb;
  181. {    int ai;
  182.  
  183.     *hostnameb = 0;
  184.     for(ai = 0; ai < ac; ai++){
  185.         if( strcmp(av[ai],"-host") == 0 ){
  186.             if(ai+1 < ac){
  187.                 strcpy(hostnameb,av[ai+1]);
  188.                 ac -= 2;
  189.                 for(;ai < ac; ai++)
  190.                     av[ai] = av[ai+2];
  191.             }
  192.             break;
  193.         }
  194.     }
  195.     return ac;
  196. }
  197. static mmsc_error_exit(message)
  198.     char *message;
  199. {
  200.     perror(message);
  201.     exit(1);
  202. }
  203.  
  204. /*////////////////////////////////////////////////////////////////////////
  205.  *    put / get server
  206.  */
  207. MMS_putserver(serv,form,a,b,c,d,e,f,g)
  208.     FILE *serv[];
  209.     char *form;
  210. {    char command[2048];
  211.     int eof;
  212.  
  213.     sprintf(command,form,a,b,c,d,e,f,g);
  214.     fprintf(serv[1],"%s",command);
  215.     eof = fflush(serv[1]);
  216.  
  217.     if( MMS_DEBUG )
  218.         printf("%s\n",command);
  219.     return eof;
  220. }
  221. MMS_getserver(serv)
  222.     FILE *serv[];
  223. {    char status[2048],body[2048];
  224.     int stat;
  225.     char resp_type;
  226.  
  227.     fgets(status,sizeof(status),serv[0]);
  228.     printf("%s",status);
  229.     fflush(stdout);
  230.  
  231.     sscanf(status,"%d %c",&stat,&resp_type);
  232.     if( resp_type && resp_type != '0' ){
  233.         while( fgets(body,sizeof(body),serv[0]) != NULL ){
  234.             printf("%s",body);
  235.             fflush(stdout);
  236. /*
  237. {
  238. int i;
  239. for(i = 0; i < 10 && body[i]; i++)
  240. fprintf(stderr,"[%c]",body[i]);
  241. fprintf(stderr,"\n");
  242. }
  243. */
  244.             if( body[0]=='.' && (body[1]=='\n'||body[1]=='\r') )
  245.                 break;
  246.         }
  247.     }
  248.     return stat;
  249. }
  250. MMS_getresponse1(serv)
  251.     FILE *serv[];
  252. {
  253. }
  254. char *
  255. MMS_getline(line,size,ifp)
  256.     char *line;
  257.     FILE *ifp;
  258. {    char *r,*p;
  259.  
  260.     r = fgets(line,size,ifp);
  261.     if( r != NULL ){
  262.         if(p = index(line,'\r')) *p = 0;
  263.         if(p = index(line,'\n')) *p = 0;
  264.         if( strcmp(line,".") == 0 )
  265.             return NULL;
  266.         if( strcmp(line,"..") == 0 )
  267.             strcpy(line,line+1);
  268.     }
  269.     return r;
  270. }
  271. FILE *MMS_getbody(ifp,sizep)
  272.     FILE *ifp;
  273.     int *sizep;
  274. {    FILE *tmp;
  275.     char line[256];
  276.     int bytes;
  277.  
  278.     if( (tmp = tmpfile()) != NULL ){
  279.         bytes = 0;
  280.         while( MMS_getline(line,sizeof(line),ifp) != NULL ){
  281.             fputs(line,tmp);
  282.             bytes += strlen(line);
  283.         }
  284.         fflush(tmp);
  285.         fseek(tmp,0,0);
  286.         if( sizep )
  287.             *sizep = bytes;
  288.     }
  289.     return tmp;
  290. }
  291.  
  292. /*////////////////////////////////////////////////////////////////////////
  293.  *    internet socket
  294.  */
  295. #include <sys/types.h>
  296. #include <sys/uio.h>
  297. #include <sys/socket.h>
  298. #include <netinet/in.h>
  299. #include <netdb.h>
  300. char *ERRMSG_open_MMS = "open_MMS_server";
  301.  
  302. static struct sockaddr_in in_sockaddr;
  303. static open_MMS_server(hostname)
  304.     char *hostname;
  305. {    int port,sock;
  306.     struct hostent *host;
  307.     struct servent *serv;
  308.  
  309.     sock = socket(AF_INET,SOCK_STREAM,6);
  310.     if( sock == -1 ) mmsc_error_exit(ERRMSG_open_MMS);
  311.  
  312.     serv = getservbyname(MMS_PORT_NAME,"tcp");
  313.     if( serv == NULL ) mmsc_error_exit(ERRMSG_open_MMS);
  314.  
  315.     port = serv->s_port;
  316.     host = gethostbyname(hostname);
  317.     if( host == NULL ) mmsc_error_exit(ERRMSG_open_MMS);
  318.  
  319.     in_sockaddr.sin_family = AF_INET;
  320.     in_sockaddr.sin_port = port;
  321.     bcopy(host->h_addr,&in_sockaddr.sin_addr,host->h_length);
  322.  
  323.     if( connect(sock,&in_sockaddr,sizeof(in_sockaddr)) == -1 )
  324.         mmsc_error_exit(ERRMSG_open_MMS);
  325.  
  326.     return sock;
  327. }
  328.  
  329. /*////////////////////////////////////////////////////////////////////////
  330.  *
  331.  */
  332. char *MMS_freshcopy();
  333.  
  334. extern char **environ;
  335. char *MMS_environ[200];
  336. MMS_putenv(name,form,a,b,c,d)
  337.     char *name,*form;
  338. {    int ei;
  339.     char oname[1024],env[4096],*ep;
  340.  
  341.     if( MMS_environ[0] == 0 ){
  342.         for(ei = 0; environ[ei]; ei++)
  343.             MMS_environ[ei] = MMS_freshcopy(environ[ei]);
  344.         MMS_environ[ei] = 0;
  345.         environ = MMS_environ;
  346.     }
  347.     for(ei = 0; environ[ei]; ei++){
  348.         sscanf(environ[ei],"%[^=]",oname);
  349.         if( strcmp(oname,name) == 0 )
  350.             break;
  351.     }
  352.     if( ep = environ[ei] )
  353.         free(ep);
  354.     if( form ){
  355.         sprintf(env,"%s=",name);
  356.         sprintf(env+strlen(env),form,a,b,c,d);
  357.         environ[ei] = MMS_freshcopy(env);
  358.     }else    environ[ei] = MMS_freshcopy("");
  359. }
  360.  
  361.  
  362. FILE *
  363. MMS_saveTempfile(fp,size)
  364.     FILE *fp;
  365. {    FILE *tmp;
  366.  
  367.     tmp = tmpfile();
  368.     MMS_copyFile(fp,tmp);
  369.     MMS_fseek(tmp,0,0);
  370.     MMS_fseek(fp,0,0);
  371.     return tmp;
  372. }
  373. MMS_copyFile(in,out)
  374.     FILE *in,*out;
  375. {    char buf[4096];
  376.     int rsize,rc;
  377.  
  378.     while( 0 < (rc = fread(buf,1,sizeof(buf),in)) )
  379.         fwrite(buf,rc,1,out);
  380.     fflush(out);
  381. }
  382.  
  383. char *HostName(){
  384.     static char hostname[128];
  385.  
  386.     if( hostname[0] == 0 )
  387.         gethostname(hostname,sizeof(hostname)-1);
  388.     return hostname;
  389. }
  390.  
  391. int PSEUDO_FILE_FD;
  392.  
  393. #ifdef hpux
  394. getwd(dir)
  395.     char *dir;
  396. {
  397.     return getcwd(dir);
  398. }
  399. setreuid(ruid,euid)
  400. {
  401.     setuid(euid);
  402. }
  403. setlinebuf(fp)
  404.     FILE *fp;
  405. {
  406.     setbuf(fp,NULL);
  407. }
  408. #endif
  409.  
  410. #if defined(_IODUMMY) || !defined(_IOSTRG)
  411. static char *dummyptr;
  412. static char *dummybase;
  413. static int dummycnt;
  414. #define PSEUDOFILE(fp)    0
  415. #define BUFSIZE(fp)    0
  416. #define BASE(fp)    dummybase
  417. #define PTR(fp)        dummyptr
  418. #define CNT(fp)        dummycnt
  419. #else
  420. #define PSEUDOFILE(fp)    (fileno(fp) < 0 && fileno(fp) == PSEUDO_FILE_FD)
  421. #define BUFSIZE(fp)    fp->_bufsiz
  422. #define BASE(fp)    fp->_base
  423. #define PTR(fp)        fp->_ptr
  424. #define CNT(fp)        fp->_cnt
  425. #endif
  426.  
  427. MMS_fseek(fp,off,from)
  428.     FILE *fp;
  429. {    int bufsize,base,disp;
  430.  
  431.     if( !PSEUDOFILE(fp) )
  432.         return fseek(fp,off,from);
  433.  
  434.     bufsize = BUFSIZE(fp);
  435.     switch(from){
  436.         case 0: base = 0;        break;
  437.         case 1: base = PTR(fp)-BASE(fp);break;
  438.         case 2: base = bufsize;        break;
  439.     }
  440.     disp = base + off;
  441.     if( disp < 0 || bufsize < disp )
  442.         return -1;
  443.  
  444.     PTR(fp) = &BASE(fp)[disp];
  445.     CNT(fp) = bufsize - disp;
  446.     return 0;
  447. }
  448. MMS_ftell(fp)
  449.     FILE *fp;
  450. {
  451.     if( !PSEUDOFILE(fp) )
  452.         return ftell(fp);
  453. /*
  454. fprintf(stderr,"ptr=%x / base=%x / off=%d / cnt=%d\n",
  455. PTR(fp),BASE(fp),PTR(fp)-BASE(fp),CNT(fp));
  456. sleep(1);
  457. */
  458.     if( CNT(fp) == 0 )
  459.         return BUFSIZE(fp);
  460.     return PTR(fp) - BASE(fp);
  461. }
  462.  
  463. MMS_seekable(fp)
  464.     FILE *fp;
  465. {
  466.     if( PSEUDOFILE(fp) )
  467.         return 1;
  468.     else    return fseek(fp,0,1) == 0;
  469. }
  470.  
  471.  
  472. char *
  473. MIME_Decoder(mp){
  474.     char *encode;
  475.  
  476.     if( encode = (char*)MMS_partContentEncode(mp) ){
  477.         if( strcasecmp(encode,"base64") == 0 )
  478.             return "mmencode -u";
  479.         if( strcasecmp(encode,"quoted-printable") == 0 )
  480.             return "mmencode -u -q";
  481.     }
  482.     return 0;
  483. }
  484.